﻿using System;
using System.ComponentModel;
using System.Reflection;

namespace PhiStore
{

    /// <summary>
    /// Enum stating which error occured
    /// </summary>
    [Serializable]
    [Flags]
    public enum ReturnCode
    {
        /// <summary>
        /// user not found
        /// </summary>
        [Description("User is unknown")]
        UnknownUser = 1,

        /// <summary>
        /// not correct pwd
        /// </summary>
        [Description("Password is incorrect")]
        WrongPassword = 2,

        /// <summary>
        /// not a verified connection - go away!
        /// </summary>
        [Description("The connection is not verified, package is not permitted")]
        ConnectionNotVerified = 4,

        /// <summary>
        /// Already exist
        /// </summary>
        [Description("Object Already exist")]
        ObjectAlreadyExist = 8,

        // No longer in use!
        //[Description("Object is currently locked by another process")]
        //ObjectIsBusy = 16,

        /// <summary>
        /// Working - do not timeout plx!
        /// </summary>
        [Description("The server is currently working on the object - Hang on!")]
        WorkingOnObject = 32,

        /// <summary>
        /// ErrorCode 404 :-)
        /// </summary>
        [Description("Object was not found")]
        ObjectNotFound = 64,

        /// <summary>
        /// Failure!
        /// </summary>
        [Description("Something really strange happened. This is the generic error. Check the logs!")]
        Failure = 128,

        /// <summary>
        /// Success
        /// </summary>
        [Description("It's all good!")]
        Success = 256,

        /// <summary>
        /// Device Errors
        /// </summary>
        [Description("The operation failed to complete on a storage device")]
        DeviceOperationFailed = 512,

        /// <summary>
        /// policy violation
        /// </summary>
        [Description("The package can't be performed since it will conflict with the policy of the object")]
        PolicyViolated = 1024,

        /// <summary>
        /// Can't support policy
        /// </summary>
        [Description("The server is unable to support the policy. Possibly due to a lack of other servers.")]
        UnableToSupportPolicy = 2048,

        /// <summary>
        /// Collection out of bounds
        /// </summary>
        [Description("Index, offset, length or count are out of bounds for this object")]
        OutOfBounds = 4096,

        /// <summary>
        /// Negotiation conflict (same bully number)
        /// </summary>
        [Description("Negotiation conflict (same bully number)")]
        NegotiationConflict = 8192,

        /// <summary>
        /// Negotiation lost
        /// </summary>
        [Description("Negotiation was lost")]
        NegotiationLost = 16384,

        /// <summary>
        /// Connection lost
        /// </summary>
        [Description("Connection was lost to server")]
        ConnectionLost = 32768
    }

    /// <summary>
    /// Static class for translating ReturnCodes into something more understandable
    /// </summary>
    public static class ReturnCodeTranslation
    {
        /// <summary>
        /// Translates ReturnCode to string
        /// </summary>
        /// <param name="code">input</param>
        /// <returns>A human-readable text</returns>
        public static string Translate(ReturnCode code)
        {
            string result = "";

            Array allCodes = Enum.GetValues(typeof(ReturnCode));
            foreach (ReturnCode c in allCodes)
            {
                if ((code & c) > 0)
                {
                    result += GetDescription(c) + " [AND] ";
                }
            }

            result = result.Remove(result.LastIndexOf(" [AND] "));
            return result;
        }

        private static string GetDescription(ReturnCode code)
        {
            Type type = code.GetType();
            MemberInfo[] memInfo = type.GetMember(code.ToString());
            if (memInfo != null && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (attrs != null && attrs.Length > 0)
                    return ((DescriptionAttribute)attrs[0]).Description;
            }
            return code.ToString();
        }
    }
}
